﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Runtime.CompilerServices;

namespace LogTest.Logging
{
    enum LogLevel
    { 
        Debug ,
        Info ,
        Warm ,
        Error,
        Fatal
    }


    class Logger : FileLogger
    {
        static FileLogger _log = new FileLogger();

        public static void Write(LogLevel l, string context)
        {
            _log.Trace(l, context);
        }

        public static void Write(LogLevel l, string context, Exception e)
        {
            _log.Trace(l, context, e);
        }

    }


    // Simlpe Async to write file log      
    class FileLogger
    {
        string _fileName = @"log.txt";
        string _folder =   @".\log\";
        string _timeFormat = @"yyyy-MM-dd HH:mm:ss:ffff";
        string _timeStamp;

        //Format: timestamp, processId|threadId [loglevel] - context
        string _logFormat = @"{0},{1}|{2} [{3}] - {4} " + System.Environment.NewLine.ToString();

        #region public method
        public FileLogger()
        {
    
        }

        public void Trace(LogLevel l, string context)
        {
            Trace(l, context, null);
        }

        public void Trace(LogLevel l, string context, Exception e)
        {
            if (null != e)
            {
                context += "," + e.ToString(); ;
            }


            string log = string.Format(_logFormat,
                                        TimeStamp,
                                        Process.GetCurrentProcess().Id,
                                        Thread.CurrentThread.ManagedThreadId,
                                        l.ToString(),
                                        context);

            new WriteFileDelegate(WriteToFile).BeginInvoke(log, null, null);
        }
        #endregion

        #region protected method
        protected string TimeStamp
        {
            get 
            {
                return DateTime.Now.ToString(_timeFormat).ToString();
            }
        }

        protected string LogFileName
        {
            get
            {
                return _fileName;
            }
        }

        protected string LogFolderName
        {
            get
            {
                CreateLogFolder();
                return _folder;
            }
        }

        protected void CreateLogFolder()
        {
            if (!Directory.Exists(_folder))
            { 
                //create folder name
                Directory.CreateDirectory(_folder);
            }            
        }


        delegate void WriteFileDelegate(string info);
        protected void WriteToFile(string context)
        {
            string filePath = LogFolderName + LogFileName;
            FileStream fs = null;
            StreamWriter sw = null;
            try
            {
                fs = new FileStream(filePath, FileMode.Append);
                sw = new StreamWriter(fs);
                sw.Write(context);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.ToString());
            }
            finally
            {
                if (null != sw)
                {
                    sw.Flush();
                    sw.Close();
                }

                if (null != fs)
                {
                    fs.Close();
                }
                
            }
        }
        #endregion

    }
}
